/**
  Builds a regular expression to match any International format for time.
  The RE can match one format or one of multiple formats.

  Format
  h        12 hour, no zero padding.
  hh       12 hour, has leading zero.
  H        24 hour, no zero padding.
  HH       24 hour, has leading zero.
  m        minutes, no zero padding.
  mm       minutes, has leading zero.
  s        seconds, no zero padding.
  ss       seconds, has leading zero.
  t        am or pm, case insensitive.
  All other characters must appear literally in the expression.

  Example
    "h:m:s t"  ->   2:5:33 PM
    "HH:mm:ss" ->  14:05:33

  @param flags  An object.
    flags.format  A string or an array of strings.  Default is "h:mm:ss t".
    flags.amSymbol  The symbol used for AM.  Default is "AM".
    flags.pmSymbol  The symbol used for PM.  Default is "PM".

  @return  A string for a regular expression for a time value.
*/
function regexpTime(flags) {
	// assign default values to missing paramters
	flags = (typeof flags == "object") ? flags : {};
	if (typeof flags.format == "undefined") { flags.format = "h:mm:ss t"; }
	if (typeof flags.amSymbol != "string") { flags.amSymbol = "AM"; }
	if (typeof flags.pmSymbol != "string") { flags.pmSymbol = "PM"; }

	// Converts a time format to a RE
	var timeRE = function(format) {
		// escape all special characters
		format = format.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");
		var amRE = flags.amSymbol.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");
		var pmRE = flags.pmSymbol.replace( /([.$?*!=:|{}\(\)\[\]\\\/^])/g, "\\$1");

		// replace tokens with Regular Expressions
		format = format.replace("hh", "(0[1-9]|1[0-2])");
		format = format.replace("h", "([1-9]|1[0-2])");
		format = format.replace("HH", "([01][0-9]|2[0-3])");
		format = format.replace("H", "([0-9]|1[0-9]|2[0-3])");
		format = format.replace("mm", "([0-5][0-9])");
		format = format.replace("m", "([1-5][0-9]|[0-9])");
		format = format.replace("ss", "([0-5][0-9])");
		format = format.replace("s", "([1-5][0-9]|[0-9])");
		format = format.replace("t", "\\s?(" + amRE + "|" + pmRE + ")\\s?" );

		return format;
	};

	// build RE for multiple time formats
	return regexpBuildGroupRE(flags.format, timeRE);
}

/**
  This is basically a utility function used by some of the RE generators.
  Builds a regular expression that groups subexpressions.
  The subexpressions are constructed by the function, re, in the second parameter.
  re builds one subexpression for each elem in the array a, in the first parameter.

  @param a  A single value or an array of values.
  @param re  A function.  Takes one parameter and converts it to a regular expression. 
  @return  A string for a regular expression that groups all the subexpressions.
*/
function regexpBuildGroupRE(a, re) {

	// case 1: a is a single value.
	if ( !( a instanceof Array ) ) { 
		return re(a);
	}

	// case 2: a is an array
	var b = [];
	for (var i = 0; i < a.length; i++) {
		// convert each elem to a RE
		b.push(re(a[i]));
	}

	 // join the REs as alternatives in a RE group.
	return "(" + b.join("|") + ")";
}